using System;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
namespace BMC.ARSystem
{
	[ClassInterface, Guid("104E0A7B-5498-471b-9F62-D73CCFF55300"), ProgId("BMC.ARSystem.AlertReceiver")]
	public class AlertReceiver
	{
		[Guid("5ae257f9-32f8-47cb-8a13-4bf3186949cc")]
		public class OnConnectEventArgs : EventArgs
		{
			private string _client;
			public string Client
			{
				get
				{
					return this._client;
				}
			}
			internal OnConnectEventArgs(string client)
			{
				this._client = client;
			}
		}
		[Guid("8745b30c-43fd-4977-8419-89036c665583")]
		public class OnDisconnectEventArgs : AlertReceiver.OnConnectEventArgs
		{
			internal OnDisconnectEventArgs(string client) : base(client)
			{
			}
		}
		[Guid("ba2d1256-4573-4321-b15a-f8310e991165")]
		public class OnDataReceivedEventArgs : AlertReceiver.OnConnectEventArgs
		{
			private AlertMessage _alertMessage;
			public AlertMessage Data
			{
				get
				{
					return this._alertMessage;
				}
			}
			internal OnDataReceivedEventArgs(string client, AlertMessage alertMessage) : base(client)
			{
				this._alertMessage = alertMessage;
			}
		}
		[Guid("d04f4cb1-7e08-4b08-a872-cc300607a639")]
		public delegate void OnConnectEventHandler(object sender, AlertReceiver.OnConnectEventArgs e);
		[Guid("efe66a40-1546-45ca-81bc-60e612f6f9dd")]
		public delegate void OnDisconnectEventHandler(object sender, AlertReceiver.OnDisconnectEventArgs e);
		[Guid("33d1a30d-c21a-43d0-b288-de4e37ac8b5e")]
		public delegate void OnDataReceivedEventHandler(object sender, AlertReceiver.OnDataReceivedEventArgs e);
		private Thread _threadProc;
		private Server _server;
		private int _alertPort = 0;
		private int _cAlertPort = 0;
		private bool _stopListening = false;
		private byte[] _ack = Encoding.get_ASCII().GetBytes("ack");
		private MyTcpListener _listener = null;
		public event AlertReceiver.OnConnectEventHandler onConnect
		{
			[MethodImpl(32)]
			add
			{
				this.onConnect = (AlertReceiver.OnConnectEventHandler)Delegate.Combine(this.onConnect, value);
			}
			[MethodImpl(32)]
			remove
			{
				this.onConnect = (AlertReceiver.OnConnectEventHandler)Delegate.Remove(this.onConnect, value);
			}
		}
		public event AlertReceiver.OnDisconnectEventHandler onDisconnect
		{
			[MethodImpl(32)]
			add
			{
				this.onDisconnect = (AlertReceiver.OnDisconnectEventHandler)Delegate.Combine(this.onDisconnect, value);
			}
			[MethodImpl(32)]
			remove
			{
				this.onDisconnect = (AlertReceiver.OnDisconnectEventHandler)Delegate.Remove(this.onDisconnect, value);
			}
		}
		public event AlertReceiver.OnDataReceivedEventHandler onDataReceived
		{
			[MethodImpl(32)]
			add
			{
				this.onDataReceived = (AlertReceiver.OnDataReceivedEventHandler)Delegate.Combine(this.onDataReceived, value);
			}
			[MethodImpl(32)]
			remove
			{
				this.onDataReceived = (AlertReceiver.OnDataReceivedEventHandler)Delegate.Remove(this.onDataReceived, value);
			}
		}
		public int AlertPort
		{
			get
			{
				return this._alertPort;
			}
		}
		public AlertReceiver(Server server)
		{
			this._server = server;
		}
		public AlertReceiver(Server server, int portListen) : this(server)
		{
			this._alertPort = portListen;
			this._cAlertPort = portListen;
		}
		public void BeginReceive()
		{
			if (this._listener != null && this._listener.MyServer != null && this._listener.MyServer.get_Blocking())
			{
				this.EndReceive();
			}
			this._stopListening = false;
			this._threadProc = new Thread(new ThreadStart(this.ThreadProcedure));
			this._threadProc.set_Name("Alert Listener");
			this._threadProc.Start();
		}
		public void EndReceive()
		{
			this._stopListening = true;
			try
			{
				this._listener.MyServer.Close();
				this._listener.Stop();
			}
			catch (SocketException ex)
			{
				if (ex.get_ErrorCode() != 10004)
				{
					throw new ARException("Error while waiting for new alerts: " + ex.get_Message());
				}
			}
			catch (Exception ex2)
			{
				throw new ARException("Error while closing alert listener: " + ex2.get_Message());
			}
			this._server.DeregisterForAlerts(this._alertPort);
			this._alertPort = 0;
			GC.Collect();
			GC.WaitForPendingFinalizers();
		}
		private void ThreadProcedure()
		{
			Trace.WriteLine("ThreadProcedure");
			this._alertPort = this._cAlertPort;
			IPAddress localaddr = Dns.Resolve("localhost").get_AddressList()[0];
			if (this._listener == null)
			{
				this._listener = new MyTcpListener(localaddr, this._alertPort);
			}
			this._listener.Start();
			if (this._alertPort == 0)
			{
				this._alertPort = ((IPEndPoint)this._listener.get_LocalEndpoint()).get_Port();
			}
			Trace.WriteLine("ThreadProcedure: Registering for AR System alerts");
			this._server.RegisterForAlerts(this._alertPort);
			while (!this._stopListening)
			{
				try
				{
					Trace.WriteLine("AcceptTcpClient()");
					MyTcpClient myTcpClient = this._listener.AcceptTcpClient();
					if (this.onConnect != null)
					{
						Trace.WriteLine("Calling on connect");
						AlertReceiver.OnConnectEventArgs e = new AlertReceiver.OnConnectEventArgs(myTcpClient.MyClient.get_RemoteEndPoint().ToString());
						this.onConnect(this, e);
					}
					Trace.WriteLine("QueueUserWorkItem");
					ThreadPool.QueueUserWorkItem(new WaitCallback(this.ReadAlertMessage), myTcpClient);
				}
				catch (SocketException ex)
				{
					Trace.WriteLine("Error while waiting for new alerts: " + ex.get_Message());
					throw new ARException("Error while waiting for new alerts: " + ex.get_Message());
				}
			}
			Trace.WriteLine("ThreadProcedure::End");
		}
		private void ReadAlertMessage(object oClient)
		{
			Trace.WriteLine("ReadAlertMessage");
			MyTcpClient myTcpClient = (MyTcpClient)oClient;
			NetworkStream stream = myTcpClient.GetStream();
			this.SendAcknowledgement(stream);
			Thread.get_CurrentThread().set_Priority(1);
			while (!stream.get_DataAvailable())
			{
			}
			Thread.get_CurrentThread().set_Priority(2);
			int bufferLen = 0;
			byte[] array = new byte[1024];
			try
			{
				bufferLen = stream.Read(array, 0, array.Length);
			}
			catch (IOException ex)
			{
				stream.Close();
				myTcpClient.MyClient.Close();
				myTcpClient.Close();
				throw new ARException("Error while reading alert: " + ex.get_Message());
			}
			this.SendAcknowledgement(stream);
			if (this.onDataReceived != null)
			{
				try
				{
					AlertMessage alertMessage = this._server.DecodeAlertMessage(array, bufferLen);
					if (!alertMessage.SourceType.Equals(AlertMessage.AlertSourceType.FirstContactIndicator))
					{
						AlertReceiver.OnDataReceivedEventArgs e = new AlertReceiver.OnDataReceivedEventArgs(myTcpClient.MyClient.get_RemoteEndPoint().ToString(), alertMessage);
						this.onDataReceived(this, e);
					}
				}
				catch (Exception var_7_E8)
				{
				}
			}
			if (this.onDisconnect != null)
			{
				AlertReceiver.OnDisconnectEventArgs e2 = new AlertReceiver.OnDisconnectEventArgs(myTcpClient.MyClient.get_RemoteEndPoint().ToString());
				this.onDisconnect(this, e2);
			}
			stream.Close();
			myTcpClient.MyClient.Close();
			myTcpClient.Close();
		}
		private void SendAcknowledgement(NetworkStream stream)
		{
			try
			{
				stream.Write(this._ack, 0, this._ack.Length);
				stream.Flush();
			}
			catch (Exception ex)
			{
				throw new ARException("Error while sending alert acknowledgment: " + ex.get_Message());
			}
		}
	}
}
